package cn.com.anypay.manager.controller;

import cn.com.anypay.manager.common.controller.BaseController;
import cn.com.anypay.manager.common.enums.ResultCode;
import cn.com.anypay.manager.common.exception.BusinessException;
import cn.com.anypay.manager.common.response.ApiResponse;
import cn.com.anypay.manager.dto.request.ChangePasswordRequestDTO;
import cn.com.anypay.manager.dto.request.LoginRequestDTO;
import cn.com.anypay.manager.dto.request.SmsLoginRequestDTO;
import cn.com.anypay.manager.dto.request.UpdateProfileRequestDTO;
import cn.com.anypay.manager.dto.request.VerifyRequestDTO;
import cn.com.anypay.manager.dto.request.WeChatBindRequestDTO;
import cn.com.anypay.manager.dto.request.WeChatLoginRequestDTO;
import cn.com.anypay.manager.dto.response.WeChatLoginUrlResponse;
import cn.com.anypay.manager.common.exception.WeChatAuthException;
import com.fasterxml.jackson.databind.ObjectMapper;
import cn.com.anypay.manager.miaoma.sysuser.SysUserEntity;
import cn.com.anypay.manager.miaoma.sysuser.SysUserService;
import cn.com.anypay.manager.miaoma.sysuserauth.SysUserAuthEntity;
import cn.com.anypay.manager.miaoma.sysuserauth.SysUserAuthService;
import cn.com.anypay.manager.miaoma.sysuserauthlog.SysUserAuthLogService;
import cn.com.anypay.manager.service.AuthService;
import cn.com.anypay.manager.service.VerificationCodeService;
import cn.com.anypay.manager.service.WeChatService;
import cn.com.anypay.manager.service.auth.model.AuthRequest;
import cn.com.anypay.manager.service.auth.model.AuthResult;
import cn.dev33.satoken.stp.StpUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 认证控制器
 * 处理用户登录、登出、权限验证等认证相关操作

 */
@Slf4j
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController extends BaseController {

    private final AuthService authService;
    private final SysUserService sysUserService;
    private final SysUserAuthService sysUserAuthService;
    private final SysUserAuthLogService sysUserAuthLogService;
    private final VerificationCodeService verificationCodeService;
    private final WeChatService weChatService;
    private final JdbcTemplate jdbcTemplate;

    /**
     * 密码编码器
     */
    private static final BCryptPasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();

    /**
     * 默认密码
     */
    private static final String DEFAULT_PASSWORD = "123456";

    /**
     * 普通用户角色ID
     */
    private static final Long DEFAULT_ROLE_ID = 15L;

    /**
     * 密码登录
     *
     * @param loginRequest 登录请求参数
     * @param servletRequest HTTP请求对象
     * @return 登录响应结果
     */
    @PostMapping("/login")
    public ApiResponse<Map<String, Object>> login(@RequestBody @Valid LoginRequestDTO loginRequest,
                                                  HttpServletRequest servletRequest) {
        log.info("用户登录请求: username={}", loginRequest.getUsername());

        // 创建认证请求
        AuthRequest authRequest = new AuthRequest("password", loginRequest.getUsername(), loginRequest.getPassword());

        // 执行认证
        AuthResult result = authService.authenticate(authRequest, servletRequest);

        if (result.isSuccess()) {
            return success(result.getData());
        } else {
            return fail(result.getErrorMessage());
        }
    }

    /**
     * 发送短信验证码
     *
     * @param request 发送验证码请求
     * @return 响应结果
     */
    @PostMapping("/sms/send")
    public ApiResponse<Void> sendSmsCode(@RequestBody @Valid SmsLoginRequestDTO.SendCodeRequest request) {
        log.info("发送短信验证码: phone={}", request.getPhone());

        try {
            authService.sendVerificationCode("sms", request.getPhone());
            return success();
        } catch (Exception e) {
            log.error("发送短信验证码失败: phone={}", request.getPhone(), e);
            return fail("发送验证码失败，请稍后重试");
        }
    }

    /**
     * 短信验证码登录
     *
     * @param smsRequest 短信登录请求
     * @param servletRequest HTTP请求对象
     * @return 登录响应结果
     */
    @PostMapping("/sms/verify")
    public ApiResponse<Map<String, Object>> smsLogin(@RequestBody @Valid SmsLoginRequestDTO.VerifyCodeRequest smsRequest,
                                                     HttpServletRequest servletRequest) {
        log.info("短信验证码登录: phone={}", smsRequest.getPhone());

        // 创建认证请求
        AuthRequest authRequest = new AuthRequest("sms", smsRequest.getPhone(), smsRequest.getCode());

        // 执行认证
        AuthResult result = authService.authenticate(authRequest, servletRequest);

        if (result.isSuccess()) {
            return success(result.getData());
        } else {
            return fail(result.getErrorMessage());
        }
    }

    /**
     * 发送邮箱验证码
     *
     * @param request 发送验证码请求
     * @return 响应结果
     */
    @PostMapping("/email/send")
    public ApiResponse<Void> sendEmailCode(@RequestBody @Valid VerifyRequestDTO.EmailCodeRequest request) {
        log.info("发送邮箱验证码: email={}", request.getEmail());

        try {
            authService.sendVerificationCode("email", request.getEmail());
            return success();
        } catch (Exception e) {
            log.error("发送邮箱验证码失败: email={}", request.getEmail(), e);
            return fail("发送验证码失败，请稍后重试");
        }
    }

    /**
     * 邮箱验证码登录
     *
     * @param emailRequest 邮箱登录请求
     * @param servletRequest HTTP请求对象
     * @return 登录响应结果
     */
    @PostMapping("/email/verify")
    public ApiResponse<Map<String, Object>> emailLogin(@RequestBody @Valid VerifyRequestDTO.EmailVerifyRequest emailRequest,
                                                       HttpServletRequest servletRequest) {
        log.info("邮箱验证码登录: email={}", emailRequest.getEmail());

        // 创建认证请求
        AuthRequest authRequest = new AuthRequest("email", emailRequest.getEmail(), emailRequest.getCode());

        // 执行认证
        AuthResult result = authService.authenticate(authRequest, servletRequest);

        if (result.isSuccess()) {
            return success(result.getData());
        } else {
            return fail(result.getErrorMessage());
        }
    }



    /**
     * 退出登录
     *
     * @param servletRequest HTTP请求对象
     * @return 响应结果
     */
    @PostMapping("/logout")
    public ApiResponse<Void> logout(HttpServletRequest servletRequest) {
        Long userId = null;
        String username = null;

        if (StpUtil.isLogin()) {
            userId = StpUtil.getLoginIdAsLong();
            SysUserEntity user = sysUserService.getById(userId);
            if (user != null) {
                username = user.getUsername();
            }
        }

        StpUtil.logout();

        if (userId != null && username != null) {
            sysUserAuthLogService.recordLogout(userId, "password", username, servletRequest);
        }

        return success();
    }

    /**
     * 获取当前用户信息
     *
     * @return 用户信息
     */
    @GetMapping("/userinfo")
    public ApiResponse<Map<String, Object>> getUserInfo() {
        Long userId = StpUtil.getLoginIdAsLong();
        SysUserEntity user = sysUserService.getById(userId);
        if (user == null) {
            return fail("用户不存在");
        }

        List<String> permissions = sysUserService.getUserPermissions(userId);

        Map<String, Object> data = new HashMap<>();
        data.put("userInfo", buildUserInfo(user));
        data.put("permissions", permissions);

        return success(data);
    }

    /**
     * 修改当前用户密码
     *
     * @param passwordRequest 修改密码请求
     * @param servletRequest HTTP请求对象
     * @return 响应结果
     */
    @PostMapping("/change-password")
    public ApiResponse<Void> changePassword(@RequestBody @Valid ChangePasswordRequestDTO passwordRequest,
                                            HttpServletRequest servletRequest) {
        log.info("用户修改密码请求");

        Long userId = StpUtil.getLoginIdAsLong();
        SysUserEntity user = sysUserService.getById(userId);
        if (user == null) {
            return fail("用户不存在");
        }

        SysUserAuthEntity authEntity = sysUserAuthService.getByAuthTypeAndKey("password", user.getUsername());
        if (authEntity == null) {
            return fail("用户认证信息不存在");
        }

        // 验证当前密码
        if (!validatePassword(passwordRequest.getOldPassword(), authEntity.getAuthCredentialValue())) {
            sysUserAuthLogService.recordPasswordChange(userId, user.getUsername(),
                "FAILED", "当前密码错误", servletRequest);
            return fail("当前密码错误");
        }

        // 更新密码
        String encodedPassword = PASSWORD_ENCODER.encode(passwordRequest.getNewPassword());
        authEntity.setAuthCredentialValue(encodedPassword);
        authEntity.setUpdatedTime(LocalDateTime.now());
        sysUserAuthService.updateById(authEntity);

        sysUserAuthLogService.recordPasswordChange(userId, user.getUsername(),
            "SUCCESS", null, servletRequest);

        log.info("用户密码修改成功: userId={}", userId);
        return success();
    }

    /**
     * 更新当前用户信息
     *
     * @param profileRequest 更新个人信息请求
     * @return 响应结果
     */
    @PostMapping("/update-profile")
    public ApiResponse<Void> updateProfile(@RequestBody @Valid UpdateProfileRequestDTO profileRequest) {
        log.info("用户更新个人信息请求");

        Long userId = StpUtil.getLoginIdAsLong();
        SysUserEntity user = sysUserService.getById(userId);
        if (user == null) {
            return fail("用户不存在");
        }

        // 检查用户名是否被其他用户使用
        if (!user.getUsername().equals(profileRequest.getUsername())) {
            SysUserEntity existUser = sysUserService.getByUsername(profileRequest.getUsername());
            if (existUser != null && !existUser.getId().equals(userId)) {
                return fail("用户名已被使用");
            }
        }

        // 更新用户信息
        user.setUsername(profileRequest.getUsername());
        user.setRealName(profileRequest.getRealName());
        sysUserService.updateById(user);

        log.info("用户信息更新成功: userId={}", userId);
        return success();
    }

    /**
     * 手机号认证
     *
     * @param phoneRequest 手机号认证请求
     * @param servletRequest HTTP请求对象
     * @return 响应结果
     */
    @PostMapping("/verify/phone")
    public ApiResponse<Void> verifyPhone(@RequestBody @Valid VerifyRequestDTO.PhoneVerifyRequest phoneRequest,
                                         HttpServletRequest servletRequest) {
        log.info("手机号认证请求: phone={}", phoneRequest.getPhone());

        if (!verificationCodeService.verifyCode("sms_login", phoneRequest.getPhone(), phoneRequest.getCode())) {
            sysUserAuthLogService.recordAuthLog(null, "phone_verify", phoneRequest.getPhone(),
                "VERIFY_CODE", "FAILED", "验证码错误或已过期", servletRequest);
            return fail("验证码错误或已过期");
        }

        Long userId = StpUtil.getLoginIdAsLong();
        SysUserEntity user = sysUserService.getById(userId);
        if (user == null) {
            return fail("用户不存在");
        }

        // 更新用户手机号并创建认证记录
        updateUserPhoneAuth(user, phoneRequest.getPhone());

        sysUserAuthLogService.recordAuthLog(userId, "phone_verify", phoneRequest.getPhone(),
            "VERIFY_CODE", "SUCCESS", null, servletRequest);

        log.info("手机号认证成功: userId={}, phone={}", userId, phoneRequest.getPhone());
        return success();
    }

    /**
     * 邮箱认证
     *
     * @param emailRequest 邮箱认证请求
     * @param servletRequest HTTP请求对象
     * @return 响应结果
     */
    @PostMapping("/verify/email")
    public ApiResponse<Void> verifyEmail(@RequestBody @Valid VerifyRequestDTO.EmailVerifyRequest emailRequest,
                                         HttpServletRequest servletRequest) {
        log.info("邮箱认证请求: email={}", emailRequest.getEmail());

        if (!verificationCodeService.verifyCode("email_verify", emailRequest.getEmail(), emailRequest.getCode())) {
            sysUserAuthLogService.recordAuthLog(null, "email_verify", emailRequest.getEmail(),
                "VERIFY_CODE", "FAILED", "验证码错误或已过期", servletRequest);
            return fail("验证码错误或已过期");
        }

        Long userId = StpUtil.getLoginIdAsLong();
        SysUserEntity user = sysUserService.getById(userId);
        if (user == null) {
            return fail("用户不存在");
        }

        // 更新用户邮箱并创建认证记录
        updateUserEmailAuth(user, emailRequest.getEmail());

        sysUserAuthLogService.recordAuthLog(userId, "email_verify", emailRequest.getEmail(),
            "VERIFY_CODE", "SUCCESS", null, servletRequest);

        log.info("邮箱认证成功: userId={}, email={}", userId, emailRequest.getEmail());
        return success();
    }

    /**
     * 测试token是否有效
     *
     * @param request HTTP请求对象
     * @return 响应结果
     */
    @GetMapping("/test-token")
    public ApiResponse<Map<String, Object>> testToken(HttpServletRequest request) {
        String tokenFromHeader = request.getHeader("Authorization");
        String tokenFromSatoken = request.getHeader("satoken");
        String tokenFromParam = request.getParameter("satoken");

        log.info("Authorization header: {}", tokenFromHeader);
        log.info("satoken header: {}", tokenFromSatoken);
        log.info("satoken param: {}", tokenFromParam);

        boolean isLogin = StpUtil.isLogin();
        log.info("Is login: {}", isLogin);

        if (isLogin) {
            Long userId = StpUtil.getLoginIdAsLong();
            String currentToken = StpUtil.getTokenValue();

            Map<String, Object> result = new HashMap<>();
            result.put("isLogin", true);
            result.put("userId", userId);
            result.put("currentToken", currentToken);

            return success(result);
        } else {
            return fail("未登录");
        }
    }

    /**
     * token调试接口
     *
     * @param request HTTP请求对象
     * @return 响应结果
     */
    @GetMapping("/debug-token")
    public ApiResponse<Map<String, Object>> debugToken(HttpServletRequest request) {
        String tokenFromHeader = request.getHeader("Authorization");
        String tokenFromSatoken = request.getHeader("satoken");
        String tokenName = StpUtil.getTokenName();

        Map<String, Object> result = new HashMap<>();
        result.put("Authorization", tokenFromHeader);
        result.put("satoken", tokenFromSatoken);
        result.put("tokenName", tokenName);

        return success(result);
    }

    // ==================== 微信认证接口 ====================

    /**
     * 获取微信登录URL
     *
     * @return 微信登录URL响应
     */
    @GetMapping("/wechat/login-url")
    public ApiResponse<WeChatLoginUrlResponse> getWeChatLoginUrl() {
        log.info("获取微信登录URL请求");

        try {
            // 生成状态参数
            String state = weChatService.generateState();
            
            // 构建微信授权URL
            String loginUrl = weChatService.buildAuthUrl(state);
            
            // 构建响应
            WeChatLoginUrlResponse response = WeChatLoginUrlResponse.builder()
                    .loginUrl(loginUrl)
                    .state(state)
                    .qrCodeContent(loginUrl)
                    .expiresIn(600L) // 10分钟有效期
                    .build();
            
            log.info("微信登录URL生成成功, state: {}", state);
            return success(response);
            
        } catch (Exception e) {
            log.error("获取微信登录URL失败", e);
            return fail("获取微信登录URL失败: " + e.getMessage());
        }
    }

    /**
     * 微信登录
     *
     * @param request 微信登录请求参数
     * @param servletRequest HTTP请求对象
     * @return 登录响应结果
     */
    @PostMapping("/wechat/login")
    public ApiResponse<Map<String, Object>> wechatLogin(@RequestBody @Valid WeChatLoginRequestDTO request,
                                                       HttpServletRequest servletRequest) {
        log.info("微信登录请求: code={}, state={}", 
                request.getCode() != null ? request.getCode().substring(0, Math.min(request.getCode().length(), 10)) + "..." : "null",
                request.getState());

        try {
            // 验证状态参数
            if (!weChatService.validateState(request.getState())) {
                log.warn("微信登录状态参数验证失败: state={}", request.getState());
                return fail("状态参数无效，请重新获取登录链接");
            }

            // 预先获取微信用户信息来获取OpenID，这是微信认证的特殊需求
            try {
                var accessToken = weChatService.getAccessToken(request.getCode());
                var weChatUserInfo = weChatService.getUserInfo(accessToken.getAccessToken(), accessToken.getOpenId());
                
                // 创建认证请求，使用OpenID作为identifier，与其他认证方式保持一致的格式
                AuthRequest authRequest = new AuthRequest("wechat", weChatUserInfo.getOpenId(), request.getCode());
                
                // 使用统一的AuthService执行认证，确保与其他认证方式一致的处理流程
                AuthResult result = authService.authenticate(authRequest, servletRequest);

                if (result.isSuccess()) {
                    // 认证成功，返回与其他认证方式一致的响应格式
                    log.info("微信登录成功: openId={}", weChatUserInfo.getOpenId());
                    return success(result.getData());
                } else {
                    // 认证失败，返回与其他认证方式一致的错误处理
                    log.warn("微信登录失败: openId={}, error={}", weChatUserInfo.getOpenId(), result.getErrorMessage());
                    return fail(result.getErrorMessage());
                }
                
            } catch (WeChatAuthException weChatException) {
                // 微信特有的异常处理，但保持与其他认证方式一致的日志格式
                log.error("微信认证异常: code={}, message={}", weChatException.getWeChatErrorCode(), weChatException.getMessage());
                
                // 记录认证失败日志，与其他认证方式保持一致
                sysUserAuthLogService.recordAuthLog(null, "wechat", request.getCode(),
                    "LOGIN", "FAILED", "微信认证异常: " + weChatException.getMessage(), servletRequest);
                
                return fail("微信登录失败: " + weChatException.getMessage());
            } catch (Exception weChatException) {
                // 网络或其他异常处理
                log.error("微信API调用失败", weChatException);
                
                // 记录认证失败日志
                sysUserAuthLogService.recordAuthLog(null, "wechat", request.getCode(),
                    "LOGIN", "FAILED", "微信API调用失败: " + weChatException.getMessage(), servletRequest);
                
                return fail("微信登录失败，请稍后重试");
            }
            
        } catch (Exception e) {
            // 最外层异常处理，确保与其他认证方式一致的错误处理
            log.error("微信登录处理失败", e);
            
            // 记录系统异常日志
            sysUserAuthLogService.recordAuthLog(null, "wechat", request.getCode(),
                "LOGIN", "FAILED", "系统异常: " + e.getMessage(), servletRequest);
            
            return fail("微信登录失败，请稍后重试");
        }
    }

    /**
     * 检查微信登录状态
     *
     * @param state 状态参数
     * @return 登录状态响应
     */
    @GetMapping("/wechat/status")
    public ApiResponse<Map<String, Object>> checkWeChatLoginStatus(@RequestParam("state") String state) {
        log.info("检查微信登录状态请求: state={}", state);

        try {
            // 验证状态参数
            if (!weChatService.validateState(state)) {
                log.warn("微信登录状态参数验证失败: state={}", state);
                return fail("状态参数无效");
            }

            // 检查登录状态
            Map<String, Object> statusInfo = weChatService.checkLoginStatus(state);
            
            log.info("微信登录状态检查完成: state={}, status={}", state, statusInfo.get("status"));
            return success(statusInfo);
            
        } catch (Exception e) {
            log.error("检查微信登录状态失败: state={}", state, e);
            
            // 返回等待状态，避免前端轮询中断
            Map<String, Object> defaultStatus = new HashMap<>();
            defaultStatus.put("status", "waiting");
            defaultStatus.put("message", "检查状态失败，请稍后重试");
            
            return success(defaultStatus);
        }
    }

    /**
     * 微信账户绑定
     *
     * @param request 微信绑定请求参数
     * @param servletRequest HTTP请求对象
     * @return 绑定响应结果
     */
    @PostMapping("/wechat/bind")
    public ApiResponse<Void> bindWeChatAccount(@RequestBody @Valid WeChatBindRequestDTO request,
                                              HttpServletRequest servletRequest) {
        log.info("微信账户绑定请求: code={}, state={}", 
                request.getCode() != null ? request.getCode().substring(0, Math.min(request.getCode().length(), 10)) + "..." : "null",
                request.getState());

        try {
            // 验证状态参数
            if (!weChatService.validateState(request.getState())) {
                log.warn("微信绑定状态参数验证失败: state={}", request.getState());
                return fail("状态参数无效，请重新获取绑定链接");
            }

            // 获取当前登录用户或指定用户
            Long userId = request.getUserId();
            if (userId == null) {
                if (!StpUtil.isLogin()) {
                    return fail("请先登录后再进行账户绑定");
                }
                userId = StpUtil.getLoginIdAsLong();
            }

            SysUserEntity user = sysUserService.getById(userId);
            if (user == null) {
                return fail("用户不存在");
            }

            // 使用微信服务来验证授权码并获取用户信息进行绑定
            // 这里不使用AuthService，因为绑定操作不是登录认证
            try {
                // 获取访问令牌
                var accessToken = weChatService.getAccessToken(request.getCode());
                
                // 获取微信用户信息
                var weChatUserInfo = weChatService.getUserInfo(accessToken.getAccessToken(), accessToken.getOpenId());
                
                // 检查该微信账户是否已被其他用户绑定
                SysUserAuthEntity existingAuth = sysUserAuthService.getByAuthTypeAndKey("wechat", weChatUserInfo.getOpenId());
                if (existingAuth != null && !existingAuth.getUserId().equals(userId)) {
                    // 记录绑定失败日志，与其他认证方式保持一致的日志格式
                    sysUserAuthLogService.recordAuthLog(userId, "wechat", weChatUserInfo.getOpenId(),
                            "BIND", "FAILED", "该微信账户已被其他用户绑定", servletRequest);
                    return fail("该微信账户已被其他用户绑定");
                }
                
                // 删除用户现有的微信绑定（如果存在）
                sysUserAuthService.removeByUserIdAndAuthType(userId, "wechat");
                
                // 创建新的微信认证记录
                SysUserAuthEntity weChatAuth = new SysUserAuthEntity();
                weChatAuth.setUserId(userId);
                weChatAuth.setAuthType("wechat");
                weChatAuth.setAuthIdentifierKey(weChatUserInfo.getOpenId());
                weChatAuth.setAuthCredentialValue(null); // 微信认证不需要密码
                weChatAuth.setStatus(1);
                weChatAuth.setIsPrimary(0);
                weChatAuth.setMaxErrorCount(5);
                weChatAuth.setErrorCount(0);
                weChatAuth.setLoginCount(0);
                weChatAuth.setCreatedTime(LocalDateTime.now());
                weChatAuth.setUpdatedTime(LocalDateTime.now());
                
                // 存储微信用户信息到扩展字段（使用JSON格式）
                Map<String, Object> weChatData = new HashMap<>();
                weChatData.put("openId", weChatUserInfo.getOpenId());
                weChatData.put("unionId", weChatUserInfo.getUnionId());
                weChatData.put("nickname", weChatUserInfo.getNickname());
                weChatData.put("headImgUrl", weChatUserInfo.getHeadImgUrl());
                weChatData.put("sex", weChatUserInfo.getSex());
                weChatData.put("country", weChatUserInfo.getCountry());
                weChatData.put("province", weChatUserInfo.getProvince());
                weChatData.put("city", weChatUserInfo.getCity());
                
                // 将微信数据转换为JSON字符串存储
                try {
                    String extraDataJson = new ObjectMapper().writeValueAsString(weChatData);
                    weChatAuth.setExtraData(extraDataJson);
                } catch (Exception jsonException) {
                    log.warn("序列化微信用户数据失败，使用简化存储", jsonException);
                    weChatAuth.setExtraData("{\"openId\":\"" + weChatUserInfo.getOpenId() + "\",\"nickname\":\"" + weChatUserInfo.getNickname() + "\"}");
                }
                
                sysUserAuthService.save(weChatAuth);
                
                // 记录绑定成功日志，与其他认证方式保持一致的日志格式
                sysUserAuthLogService.recordAuthLog(userId, "wechat", weChatUserInfo.getOpenId(),
                        "BIND", "SUCCESS", "微信账户绑定成功", servletRequest);
                
                log.info("微信账户绑定成功: userId={}, openId={}, nickname={}", 
                        userId, weChatUserInfo.getOpenId(), weChatUserInfo.getNickname());
                return success();
                
            } catch (WeChatAuthException weChatException) {
                // 微信特有的异常处理，但保持与其他认证方式一致的日志格式
                log.error("微信认证异常: userId={}, code={}, message={}", 
                        userId, weChatException.getWeChatErrorCode(), weChatException.getMessage());
                
                // 记录绑定失败日志，与其他认证方式保持一致
                sysUserAuthLogService.recordAuthLog(userId, "wechat", request.getCode(),
                        "BIND", "FAILED", "微信认证异常: " + weChatException.getMessage(), servletRequest);
                
                return fail("微信账户绑定失败: " + weChatException.getMessage());
            } catch (Exception e) {
                // 其他异常处理，确保与其他认证方式一致的错误处理
                log.error("微信账户绑定失败: userId={}", userId, e);
                
                // 记录绑定失败日志
                sysUserAuthLogService.recordAuthLog(userId, "wechat", request.getCode(),
                        "BIND", "FAILED", "微信账户绑定失败: " + e.getMessage(), servletRequest);
                
                return fail("微信账户绑定失败，请稍后重试");
            }
            
        } catch (Exception e) {
            // 最外层异常处理，确保与其他认证方式一致的错误处理
            log.error("微信账户绑定处理失败", e);
            
            // 记录系统异常日志
            Long userId = request.getUserId();
            if (userId == null && StpUtil.isLogin()) {
                userId = StpUtil.getLoginIdAsLong();
            }
            
            if (userId != null) {
                sysUserAuthLogService.recordAuthLog(userId, "wechat", request.getCode(),
                        "BIND", "FAILED", "系统异常: " + e.getMessage(), servletRequest);
            }
            
            return fail("微信账户绑定失败，请稍后重试");
        }
    }

    // ==================== 私有方法 ====================

    /**
     * 根据手机号获取或创建用户
     */
    private SysUserEntity getOrCreateUserByPhone(String phone, HttpServletRequest servletRequest) {
        SysUserEntity user = sysUserService.getByPhone(phone);

        if (user == null) {
            log.info("手机号{}未注册，自动创建新用户", phone);
            user = createNewUserByPhone(phone);
            log.info("自动创建用户成功: userId={}, phone={}", user.getId(), user.getPhone());

            sysUserAuthLogService.recordAuthLog(user.getId(), "sms", phone,
                "USER_CREATE", "SUCCESS", "短信登录自动创建用户", servletRequest);
        }

        return user;
    }

    /**
     * 根据邮箱获取或创建用户
     */
    private SysUserEntity getOrCreateUserByEmail(String email, HttpServletRequest servletRequest) {
        SysUserEntity user = sysUserService.getByEmail(email);

        if (user == null) {
            log.info("邮箱{}未注册，自动创建新用户", email);
            user = createNewUserByEmail(email);
            log.info("自动创建用户成功: userId={}, email={}", user.getId(), user.getEmail());

            sysUserAuthLogService.recordAuthLog(user.getId(), "email", email,
                "USER_CREATE", "SUCCESS", "邮箱登录自动创建用户", servletRequest);
        }

        return user;
    }

    /**
     * 根据手机号创建新用户
     */
    @Transactional(rollbackFor = Exception.class)
    private SysUserEntity createNewUserByPhone(String phone) {
        // 创建用户基本信息
        SysUserEntity user = buildNewUser(phone, phone, "用户" + phone.substring(phone.length() - 4));
        user.setPhone(phone);
        sysUserService.save(user);

        // 创建认证记录
        createAuthRecord(user.getId(), "sms", phone, null, true);
        createAuthRecord(user.getId(), "password", phone, PASSWORD_ENCODER.encode(DEFAULT_PASSWORD), false);

        // 分配默认角色
        assignDefaultRole(user.getId());

        return user;
    }

    /**
     * 根据邮箱创建新用户
     */
    @Transactional(rollbackFor = Exception.class)
    private SysUserEntity createNewUserByEmail(String email) {
        String nickname = email.substring(0, email.indexOf('@'));
        SysUserEntity user = buildNewUser(email, email, "用户" + nickname);
        user.setEmail(email);
        sysUserService.save(user);

        // 创建认证记录
        createAuthRecord(user.getId(), "email", email, null, true);
        createAuthRecord(user.getId(), "password", email, PASSWORD_ENCODER.encode(DEFAULT_PASSWORD), false);

        // 分配默认角色
        assignDefaultRole(user.getId());

        return user;
    }

    /**
     * 构建新用户对象
     */
    private SysUserEntity buildNewUser(String username, String identifier, String realName) {
        SysUserEntity user = new SysUserEntity();
        user.setUsername(username);
        user.setRealName(realName);
        user.setStatus(1);
        user.setCreatedTime(LocalDateTime.now());
        user.setUpdatedTime(LocalDateTime.now());
        user.setDeleted(0);
        return user;
    }

    /**
     * 创建认证记录
     */
    private void createAuthRecord(Long userId, String authType, String identifier, String credential, boolean isPrimary) {
        SysUserAuthEntity authEntity = new SysUserAuthEntity();
        authEntity.setUserId(userId);
        authEntity.setAuthType(authType);
        authEntity.setAuthIdentifierKey(identifier);
        authEntity.setAuthCredentialValue(credential);
        authEntity.setStatus(1);
        authEntity.setIsPrimary(isPrimary ? 1 : 0);
        authEntity.setMaxErrorCount(5);
        authEntity.setErrorCount(0);
        authEntity.setLoginCount(0);
        authEntity.setCreatedTime(LocalDateTime.now());
        authEntity.setUpdatedTime(LocalDateTime.now());

        try {
            sysUserAuthService.save(authEntity);
            log.info("创建{}认证记录成功: userId={}, identifier={}", authType, userId, identifier);
        } catch (Exception e) {
            log.error("创建{}认证记录失败: userId={}, identifier={}", authType, userId, identifier, e);
            sysUserService.removeById(userId);
            throw new BusinessException(ResultCode.BUSINESS_ERROR, "创建用户认证信息失败", e);
        }
    }

    /**
     * 分配默认角色
     */
    private void assignDefaultRole(Long userId) {
        try {
            createUserRoleRelation(userId, DEFAULT_ROLE_ID);
            log.info("为用户{}分配普通用户角色成功，角色ID={}", userId, DEFAULT_ROLE_ID);
        } catch (Exception e) {
            log.error("为用户{}分配角色失败", userId, e);
        }
    }

    /**
     * 创建用户-角色关联
     */
    private void createUserRoleRelation(Long userId, Long roleId) {
        try {
            String sql = "INSERT INTO t_sys_user_role (user_id, role_id, created_time) VALUES (?, ?, ?)";
            jdbcTemplate.update(sql, userId, roleId, LocalDateTime.now());
            log.info("成功为用户{}分配角色{}", userId, roleId);
        } catch (Exception e) {
            log.error("创建用户-角色关联失败: userId={}, roleId={}", userId, roleId, e);
        }
    }

    /**
     * 更新用户手机号认证
     */
    private void updateUserPhoneAuth(SysUserEntity user, String phone) {
        user.setPhone(phone);
        sysUserService.updateById(user);

        // 删除现有手机号认证记录
        sysUserAuthService.removeByUserIdAndAuthType(user.getId(), "phone");

        // 创建新的手机号认证记录
        createAuthRecord(user.getId(), "phone", phone, null, false);
        log.info("手机号认证记录已创建: userId={}, phone={}", user.getId(), phone);
    }

    /**
     * 更新用户邮箱认证
     */
    private void updateUserEmailAuth(SysUserEntity user, String email) {
        user.setEmail(email);
        sysUserService.updateById(user);

        // 删除现有邮箱认证记录
        sysUserAuthService.removeByUserIdAndAuthType(user.getId(), "email");

        // 创建新的邮箱认证记录
        createAuthRecord(user.getId(), "email", email, null, false);
        log.info("邮箱认证记录已创建: userId={}, email={}", user.getId(), email);
    }

    /**
     * 构建用户信息
     */
    private Map<String, Object> buildUserInfo(SysUserEntity user) {
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("username", user.getUsername());
        userInfo.put("realName", user.getRealName());
        userInfo.put("email", user.getEmail());
        userInfo.put("phone", user.getPhone());
        userInfo.put("avatar", user.getAvatar());
        return userInfo;
    }

    /**
     * 验证密码是否匹配
     *
     * @param rawPassword     原始密码
     * @param encodedPassword 加密后的密码
     * @return 是否匹配
     */
    private boolean validatePassword(String rawPassword, String encodedPassword) {
        return PASSWORD_ENCODER.matches(rawPassword, encodedPassword);
    }
}
